#include "strategies/MinOppGainDiscardStrategy.h"
#include "Query.h"

int MinOppGainDiscardStrategy::pickDiscard(CCardStack* hand, bool lastCardPicked, const GameState* gameState) {
    int ret = 0;
    int otherPlayer = (gameState->getCurrPlayer() + 1) % 2;
    int handRange = lastCardPicked ? 3 : 4;
    CCardStack oppHand = gameState->getCardsPickedUpAndHeldByPlayer(otherPlayer);
    Query::debugOut(string("Opponent hand: ") + string(oppHand.Initials()) + string("\n"), 2);
    int numTies = 1;
    // Make decision
    int minGain = Query::maxGainFromCard(oppHand, hand->at(ret));
    for (int i = 1; i < handRange; i++) {
        int cardGain = Query::maxGainFromCard(oppHand, hand->at(i));
        if (cardGain == minGain) {
            numTies++;
            if (hand->at(i).Value() < hand->at(ret).Value()) {
                ret = i;
            }
        }
        else if (cardGain < minGain) {
            minGain = cardGain;
            ret = i;
            numTies = 1;
        }
    }
    // Calculate decision certainty
    int decisionSuit = hand->at(ret).Suit();
    int unknownOppCards = 3 - oppHand.Size();
    if (unknownOppCards > 0) {
        CCardStack possibleCards = gameState->getUnknownCards(gameState->getCurrPlayer());
        if (possibleCards.Size() > 0) {
            int decisionSuitCount = 0;
            for (CONST_VI ci = possibleCards.begin(); ci != possibleCards.end(); ci++) {
                if (ci->Suit() == decisionSuit) {
                    decisionSuitCount++;
                }
            }
            int probCorrector = (unknownOppCards < 3) ? (unknownOppCards-1) : unknownOppCards;
            float probHigherGain = (float) (unknownOppCards*decisionSuitCount - probCorrector) / possibleCards.Size();
            decisionCertainty = (int) (100*(1.0f - probHigherGain));
        }
        else {
            decisionCertainty = 100 / numTies;
        }
    }
    else {
        decisionCertainty = 100 / numTies;
    }
    Query::debugOut(string("Discard decision certainty: "), 2);
    Query::debugValue(decisionCertainty, 2);
    return ret;
}

//bool oppHasSuit[4] = {false};
//int numOppSuits = 0;
//for (CONST_VI ci = oppHand.begin(); ci != oppHand.end(); ci++) {
//    int suit = ci->Suit();
//    if (!oppHasSuit[suit]) {
//        oppHasSuit[suit] = true;
//        numOppSuits++;
//    }
//}
//CCardStack freeCards;
//for (int i = 0; i < handRange; i++) {
//    const CCard& handCard = hand->at(i);
//    if (!oppHasSuit[handCard.Suit()]) {
//        freeCards.Push(CCard(handCard.GetIndex()));
//    }
//}
//if (freeCards.Empty()) {
//    int gainFromCard[handRange];
//    if (oppHand.Size == 1 || (oppHand.Size() == 2 && numOppSuits == 1)) {
//        CCardStack toMinimize;
//        for (int i = 0; i < handRange; i++) {
//            toMinimize.Push(CCard(hand->at(i).GetIndex()));
//        }
//        ret = Query::minValueIndex(toMinimize);
//        int numTies = 0;
//        for (int i = 0; i < handRange; i++) {
//            if (toMinimize.at(i).Value() == toMinimize.at(ret).Value()) {
//                numTies++;
//            }
//        }
//        decisionCertainty = 100 / numTies;
//    }
//    else if (oppHand.Size() == 2) {
//
//    }
//}
